home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ue312src.zip / ANSI.C < prev    next >
C/C++ Source or Header  |  1993-04-21  |  13KB  |  594 lines

  1. /*
  2.  * The routines in this file provide support for ANSI style terminals
  3.  * over a serial line. The serial I/O services are provided by routines in
  4.  * termio.c. It compiles into nothing if not an ANSI device.
  5.  */
  6.  
  7. #define    termdef    1            /* don't define term external */
  8.         /* don't define term external */
  9.  
  10. #include        <stdio.h>
  11. #include    "estruct.h"
  12. #include    "eproto.h"
  13. #include        "edef.h"
  14. #include    "elang.h"
  15.  
  16. #if     ANSI
  17.  
  18. #if    PROTO
  19. int PASCAL NEAR fnclabel(int f, int n);
  20. int PASCAL NEAR readparam( int *v);
  21. void PASCAL NEAR dobbnmouse(void);
  22. void PASCAL NEAR docsi( int oh);
  23. void PASCAL NEAR ttputs(char *string);
  24. #else
  25. int PASCAL NEAR fnclabel();
  26. int PASCAL NEAR readparam();
  27. void PASCAL NEAR dobbnmouse();
  28. void PASCAL NEAR docsi();
  29. void PASCAL NEAR ttputs();
  30. #endif
  31.  
  32. #if VMS
  33. #include ttdef
  34. #include tt2def
  35.  
  36. /*
  37.     This structure, along with ttdef.h, is good for manipulating
  38.     terminal characteristics.
  39. */
  40. typedef struct
  41. {/* Terminal characteristics buffer */
  42.     unsigned char class, type;
  43.     unsigned short width;
  44.     unsigned tt1 : 24;
  45.     unsigned char page;
  46.     unsigned long tt2;
  47. } TTCHAR;
  48. extern NOSHARE TTCHAR orgchar;            /* Original characteristics */
  49. #endif
  50.  
  51. #define NROW    25                      /* Screen size.                 */
  52. #define NCOL    80                      /* Edit if you want to.         */
  53. #define    NPAUSE    100            /* # times thru update to pause */
  54. #define    MARGIN    8            /* size of minimim margin and    */
  55. #define    SCRSIZ    64            /* scroll size for extended lines */
  56. #define BEL     0x07                    /* BEL character.               */
  57. #define ESC     0x1B                    /* ESC character.               */
  58.  
  59. /* Forward references.          */
  60. extern int PASCAL NEAR ansimove();
  61. extern int PASCAL NEAR ansieeol();
  62. extern int PASCAL NEAR ansieeop();
  63. extern int PASCAL NEAR ansibeep();
  64. extern int PASCAL NEAR ansiopen();
  65. extern int PASCAL NEAR ansirev();
  66. extern int PASCAL NEAR ansiclose();
  67. extern int PASCAL NEAR ansikopen();
  68. extern int PASCAL NEAR ansikclose();
  69. extern int PASCAL NEAR ansicres();
  70. extern int PASCAL NEAR ansiparm();
  71. extern int PASCAL NEAR ansigetc();
  72.  
  73. #if    COLOR
  74. extern int PASCAL NEAR ansifcol();
  75. extern int PASCAL NEAR ansibcol();
  76. static int rev_state = FALSE;
  77.  
  78. static int cfcolor = -1;    /* current foreground color */
  79. static int cbcolor = -1;    /* current background color */
  80.  
  81. #if    AMIGA
  82. /* Apparently the AMIGA does not follow the ANSI standards as
  83.  * regards to colors....maybe because of the default pallette
  84.  * settings?  Color translation table needed.
  85.  */
  86.  
  87. int coltran[16] = {2,  3,  5,  7, 0,  4,  6,  1,
  88.            8, 12, 10, 14, 9, 13, 11, 15};
  89. #endif
  90. #endif
  91.  
  92. /*
  93.  * Standard terminal interface dispatch table. Most of the fields point into
  94.  * "termio" code.
  95.  */
  96. NOSHARE TERM term    = {
  97.     NROW-1,
  98.         NROW-1,
  99.         NCOL,
  100.         NCOL,
  101.     0, 0,
  102.     MARGIN,
  103.     SCRSIZ,
  104.     NPAUSE,
  105.         ansiopen,
  106.         ansiclose,
  107.     ansikopen,
  108.     ansikclose,
  109.         ansigetc,
  110.         ttputc,
  111.         ttflush,
  112.         ansimove,
  113.         ansieeol,
  114.         ansieeop,
  115.         ansieeop,
  116.         ansibeep,
  117.     ansirev,
  118.     ansicres
  119. #if    COLOR
  120.     , ansifcol,
  121.     ansibcol
  122. #endif
  123. };
  124.  
  125. #if    COLOR
  126. PASCAL NEAR ansifcol(color)        /* set the current output color */
  127.  
  128. int color;    /* color to set */
  129.  
  130. {
  131.     if (color == cfcolor)
  132.         return;
  133.     ttputc(ESC);
  134.     ttputc('[');
  135. #if    MSDOS
  136.     if (color > 7) {
  137.         ansiparm(1);
  138.         ttputc(';');
  139.         ansiparm((color&7)+30);
  140.     } else {
  141.         ansiparm(0);
  142.         ttputc(';');
  143.         ansiparm(cbcolor+40);
  144.         ttputc(';');
  145.         ansiparm(color+30);
  146.     }
  147. #else
  148. #if    AMIGA
  149.     ansiparm(coltran[color]+30);
  150. #else
  151.     ansiparm(color+30);
  152. #endif
  153. #endif
  154.     ttputc('m');
  155.     cfcolor = color;
  156. }
  157.  
  158. PASCAL NEAR ansibcol(color)        /* set the current background color */
  159.  
  160. int color;    /* color to set */
  161.  
  162. {
  163.     if (color == cbcolor)
  164.         return;
  165.     ttputc(ESC);
  166.     ttputc('[');
  167. #if    AMIGA
  168.     ansiparm(coltran[color]+40);
  169. #else
  170.     ansiparm((color&7)+40);
  171. #endif
  172.     ttputc('m');
  173.         cbcolor = color;
  174. }
  175. #endif
  176.  
  177. PASCAL NEAR ansimove(row, col)
  178. {
  179.         ttputc(ESC);
  180.         ttputc('[');
  181.         ansiparm(row+1);
  182.         ttputc(';');
  183.         ansiparm(col+1);
  184.         ttputc('H');
  185. }
  186.  
  187. PASCAL NEAR ansieeol()
  188. {
  189.         ttputc(ESC);
  190.         ttputc('[');
  191.         ttputc('K');
  192. }
  193.  
  194. PASCAL NEAR ansieeop()
  195. {
  196. #if    COLOR
  197.     ansifcol(gfcolor);
  198.     ansibcol(gbcolor);
  199. #endif
  200.         ttputc(ESC);
  201.         ttputc('[');
  202.         ttputc('0');
  203.         ttputc('J');
  204. }
  205.  
  206. PASCAL NEAR ansirev(state)        /* change reverse video state */
  207.  
  208. int state;    /* TRUE = reverse, FALSE = normal */
  209.  
  210. {
  211. #if    COLOR
  212.     int ftmp, btmp;        /* temporaries for colors */
  213.  
  214.     if (state != rev_state) {
  215.         ftmp = cfcolor;
  216.         btmp = cbcolor;
  217.         cfcolor = -1;
  218.         cbcolor = -1;
  219.         ansifcol(btmp);
  220.         ansibcol(ftmp);
  221.         rev_state = state;
  222.     }
  223. #else
  224.     ttputc(ESC);
  225.     ttputc('[');
  226.     ttputc(state ? '7': '0');
  227.     ttputc('m');
  228. #endif
  229. }
  230.  
  231. PASCAL NEAR ansicres()    /* change screen resolution */
  232.  
  233. {
  234.     return(TRUE);
  235. }
  236.  
  237. #if    PROTO
  238. PASCAL NEAR spal(char *dummy)        /* change pallette settings */
  239. #else
  240. PASCAL NEAR spal(dummy)        /* change pallette settings */
  241.  
  242. char *dummy;
  243. #endif
  244.  
  245. {
  246.     /* none for now */
  247. }
  248.  
  249. PASCAL NEAR ansibeep()
  250. {
  251.         ttputc(BEL);
  252.         ttflush();
  253. }
  254.  
  255. PASCAL NEAR ansiparm(n)
  256. register int    n;
  257. {
  258.         register int q,r;
  259.  
  260.         q = n/10;
  261.         if (q != 0) {
  262.         r = q/10;
  263.         if (r != 0) {
  264.             ttputc((r%10)+'0');
  265.         }
  266.         ttputc((q%10) + '0');
  267.         }
  268.         ttputc((n%10) + '0');
  269. }
  270.  
  271. PASCAL NEAR ansiopen()
  272. {
  273. #if     V7 | USG | AUX | HPUX8 | HPUX9 | BSD | SUN | XENIX
  274.         register char *cp;
  275.         char *getenv();
  276.  
  277.         if ((cp = getenv("TERM")) == NULL) {
  278.                 puts(TEXT4);
  279. /*                   "Shell variable TERM not defined!" */
  280.                 meexit(1);
  281.         }
  282.         if (strcmp(cp, "vt100") != 0 && strcmp(cp,"vt200") != 0 &&
  283.                     strcmp(cp,"vt300") != 0) {
  284.                 puts(TEXT5);
  285. /*                   "Terminal type not 'vt100'!" */
  286.                 meexit(1);
  287.         }
  288. #endif
  289. #if    MOUSE & ( V7 | USG | AUX | HPUX8 | HPUX9 | BSD | SUN | XENIX | VMS)
  290. /*
  291.     If this is an ansi terminal of at least DEC level
  292.     2 capability, some terminals of this level, such as the "Whack"
  293.     emulator, the VWS terminal emulator, and some versions of XTERM,
  294.     support access to the workstation mouse via escape sequences.  In
  295.     addition, any terminal that conforms to level 2 will, at very least,
  296.     IGNORE the escape sequences for the mouse.
  297. */
  298.     {
  299.     char *s;
  300.  
  301.     s = getenv( "MICROEMACS$MOUSE_ENABLE");
  302.     if( !s) s = "\033[1)u\033[1;3'{\033[1;2'z";
  303.     ttputs( s);
  304.     }
  305. #endif
  306.     strcpy(sres, "NORMAL");
  307.     revexist = TRUE;
  308.         ttopen();
  309.  
  310. #if    KEYPAD
  311.     ttputc(ESC);
  312.     ttputc('=');
  313. #endif
  314. }
  315.  
  316. PASCAL NEAR ansiclose()
  317.  
  318. {
  319. #if    COLOR
  320.     ansifcol(7);
  321.     ansibcol(0);
  322. #endif
  323. #if    MOUSE & ( V7 | USG | AUX | HPUX8 | HPUX9 | BSD | SUN | XENIX | VMS)
  324.     {
  325.         char *s;
  326.  
  327.         s = getenv( "MICROEMACS$MOUSE_DISABLE");
  328.  
  329.         if( !s)        /* Regular DEC workstation */
  330.             s = "\033[0'{\033[0;0'z";
  331.         ttputs( s);
  332.     }
  333. #endif
  334. #if    KEYPAD
  335. #if     VMS
  336.     if ((orgchar.tt2 & TT2$M_APP_KEYPAD)==0)
  337. #endif
  338.     {
  339.         ttputc(ESC);
  340.         ttputc('>');
  341.     }
  342. #endif
  343.     ttclose();
  344. }
  345.  
  346. PASCAL NEAR ansikopen()    /* open the keyboard (a noop here) */
  347.  
  348. {
  349. }
  350.  
  351. PASCAL NEAR ansikclose()    /* close the keyboard (a noop here) */
  352.  
  353. {
  354. }
  355.  
  356. #if     V7 | USG | AUX | HPUX8 | HPUX9 | BSD | SUN | XENIX | VMS
  357. /***
  358.  *  ttputs  -  Send a string to ttputc
  359.  *
  360.  *  Nothing returned
  361.  ***/
  362. void PASCAL NEAR ttputs(string)
  363. char * string;                /* String to write        */
  364. {
  365.     if (string)
  366.         while (*string != '\0')
  367.             ttputc(*string++);
  368. }
  369.  
  370. /*
  371.     On the "real" ansi terminals, used on "mainframe" type
  372.     terminal/CPU connections of the above operating systems, we do
  373.     conversion from VT100/VT200 style function keys into the Emacs
  374.     standard key sequence form.
  375. */
  376. static unsigned char inbuffer[ 10];
  377. static int inpos=0;
  378. static int inlen=0;
  379.  
  380. NOSHARE int mouserow, mousecol;
  381.  
  382. int PASCAL NEAR readparam( v)    /* Read an ansi parameter */
  383. int *v;    /* Place to put parameter value */
  384. {
  385.     int ch;
  386.  
  387.     *v = 0;
  388.     for(;;)
  389.     { /* Read in a number */
  390.        ch = ttgetc();
  391.     if( ch>='0' && ch<='9') *v = 10 * *v + (ch - '0');
  392.     else return( ch);
  393.     }
  394. }
  395.  
  396. /*
  397.  * Handle the CSI (<esc>[) and SS3 (<esc>O) sequences.
  398.  * Static arrays are set up to translate the ANSI escape sequence
  399.  * into the MicroEMACS keycode.
  400.  *
  401.  * The 'x' in the arrays keypad[] and dec_fnkey[] are merely placeholders.
  402.  */
  403. void PASCAL NEAR docsi( oh)
  404. int oh;
  405. {
  406.     static char crsr[4] = {'P', 'N', 'F', 'B'};
  407.     static char keypad[14] = {',', '-', '.', 'x', '0', '1', '2', '3',
  408.                   '4', '5', '6', '7', '8', '9'};
  409.  
  410.     static char dec_fnkey[32] = {'x', 'S', 'C', 'D', '@', 'Z', 'V', 'x',
  411.                      '1', '2', '3', '4', '5', 'x', '6', '7',
  412.                  '8', '9', '0', 'x', '1', '2', '3', '4',
  413.                  'x', '5', '6', 'x', '7', '8', '9', '0',
  414.                 };
  415.  
  416.     unsigned int params[ 5];
  417.     int i;
  418.     unsigned int ch;
  419.  
  420.     params[ 0] = params[ 1] = params[ 2] = params[ 3] = params[ 4] = 0;
  421.     for( i=0;;)
  422.     {
  423.     ch = readparam( ¶ms[ i]);
  424.     if( ch >= '@')
  425.     { /* This ends the sequence, check for the ones we care about */
  426.         mousecol = params[ 0];
  427.         mouserow = params[ 1];
  428.         if( ch == 'R' && oh != 'O')
  429.         {    /* Cursor pos report */
  430.         inbuffer[ inlen++] = 0x0;
  431.         inbuffer[ inlen++] = MOUS>>8;
  432.         inbuffer[ inlen++] = mouserow;
  433.         inbuffer[ inlen++] = mousecol;
  434.         inbuffer[ inlen++] = '1';
  435.         }
  436.         else if( ch == '~')
  437.         {/* LK201 function key */
  438.         inbuffer[ inlen++] = 0x0;
  439.         if (params[0] > 8) params[0] -= 3;
  440.         if (params[0] > 18)
  441.             inbuffer[ inlen++] = (SHFT|SPEC)>>8;
  442.         else
  443.             inbuffer[ inlen++] = SPEC>>8;
  444.         inbuffer[ inlen++] = dec_fnkey[ params[ 0]];
  445.         }
  446.         else if( ch == 'w' && oh != 'O')
  447.         { /* mouse report */
  448.         mousecol = params[ 3]-1;
  449.         mouserow = params[ 2]-1;
  450.         inbuffer[ inlen++] = 0x0;
  451.         inbuffer[ inlen++] = MOUS>>8;
  452.         inbuffer[ inlen++] = mousecol;
  453.         inbuffer[ inlen++] = mouserow;
  454.         inbuffer[ inlen++] = ('a'-2)+params[ 0];
  455.         }
  456.         else if( ch == 'd' && oh != 'O')
  457.         { /* Pixette mouse report */
  458.         mousecol = params[ 0]-1;
  459.         mouserow = params[ 1]-1;
  460.         inbuffer[ inlen++] = 0x0;
  461.         inbuffer[ inlen++] = MOUS>>8;
  462.         inbuffer[ inlen++] = mousecol;
  463.         inbuffer[ inlen++] = mouserow;
  464.         inbuffer[ inlen++] = ('a'-2)+params[ 2];
  465.         }
  466.         else /* Ordinary keypad or arrow key */
  467.         {
  468.         inbuffer[ inlen++] = 0x0;
  469.         if( ch <= 'D' && ch >= 'A') /* Arrow keys.*/
  470.         {
  471.             inbuffer[ inlen++] = (SPEC)>>8;
  472.             inbuffer[ inlen++] = crsr[ ch - 'A'];
  473.         }
  474.         else if (ch <= 'S' && ch >= 'P')    /* PF keys.*/
  475.         {
  476.             inbuffer[ inlen++] = (SPEC|CTRL)>>8;
  477.             inbuffer[ inlen++] = ch - ('P' - '1');
  478.         }
  479.         else
  480.         {
  481.             inbuffer[ inlen++] = (ALTD)>>8;
  482.             if (ch == 'M')
  483.             inbuffer[ inlen++] = 'E';
  484.             else
  485.             inbuffer[ inlen++] = keypad[ ch - 'l'];
  486.         }
  487.         }
  488.         return;
  489.     }
  490.     if( i<5) i++;
  491.     }
  492. }
  493.  
  494. void PASCAL NEAR dobbnmouse()
  495. {
  496.     int params[ 5];
  497.     int i, ch;
  498.     static char prev = 0;
  499.     int event, flags;
  500.  
  501.     params[ 0] = 0;
  502.     params[ 1] = 0;
  503.     params[ 2] = 0;
  504.     params[ 3] = 0;
  505.     params[ 4] = 0;
  506.     for( i=0;;)
  507.     {
  508.         /* Is the sequence finished?
  509.          * check for the ones we care about.
  510.          */
  511.         if( (ch = readparam( ¶ms[ i])) >= '@')
  512.         {
  513.             mousecol = (params[ 1]+4)/9;
  514.             mouserow = (1015-params[ 2])/16;
  515.             flags = params[ 3] & 7;
  516.             event = flags ^ prev;
  517.             prev = flags;
  518.             flags = ((flags & event) == 0);
  519.             event = flags + (6 - (event & 6));
  520.             if( ch == 'c')
  521.             {    /* Cursor pos report */
  522.                 inbuffer[ inlen++] = 0x0;
  523.                 inbuffer[ inlen++] = MOUS>>8;
  524.                 inbuffer[ inlen++] = mousecol;
  525.                 inbuffer[ inlen++] = mouserow;
  526.                 inbuffer[ inlen++] = ('a'-2)+event;
  527.             }
  528.             return;
  529.         }
  530.     if( i<5) i++;
  531.     }
  532. }
  533.  
  534. /*
  535.  *    Read a keystroke from the terminal.  Interpret escape sequences
  536.  *    that come from function keys, mouse reports, and cursor location
  537.  *    reports, and return them using Emacs's coding of these events.
  538.  */
  539. PASCAL NEAR ansigetc()
  540. {
  541.     int ch;
  542.  
  543.     for(;;)
  544.     {/* Until we get a character to return */
  545.     if( inpos < inlen)
  546.     { /* Working out a multi-byte input sequence */
  547.         return( inbuffer[ inpos++]);
  548.     }
  549.     inpos = 0;
  550.     inlen = 0;
  551.     ch = ttgetc();
  552.     if( ch == 27)
  553.     { /* ESC, see if sequence follows */
  554. /*
  555.     If the "terminator" is ESC, and if we are currently reading a
  556.     string where the terminator is ESC, then return the ESC and do
  557.     not allow function keys or mouse to operate properly.  This
  558.     makes VT100 users much happier.
  559. */
  560.         ch = ttgetc_shortwait();
  561.         if( ch < 0) return( 27);    /* Wasn't a function key */
  562.         if( ch == '[') docsi( ch);
  563.         else if( ch == ':') dobbnmouse();
  564.         else if( ch == 'O') docsi( ch);
  565.         else
  566.         { /* This isn't an escape sequence, return it unmodified */
  567.         inbuffer[ inlen++] = ch;
  568.         return( 27);
  569.         }
  570.     }
  571.     else if( ch == 27+128) docsi( ch);
  572.     else return( ch);
  573.     }
  574. }
  575. #else
  576. PASCAL NEAR  ansigetc() {return( ttgetc());}
  577. #endif
  578.  
  579. #if    FLABEL
  580. int PASCAL NEAR fnclabel(f, n)        /* label a function key */
  581.  
  582. int f,n;    /* default flag, numeric argument [unused] */
  583.  
  584. {
  585.     /* on machines with no function keys...don't bother */
  586.     return(TRUE);
  587. }
  588. #endif
  589. #else
  590. ansihello()
  591. {
  592. }
  593. #endif
  594.